package com.bckj.freshnow.order.trade.execution.create;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.cola.extension.BizScenario;
import com.alibaba.cola.extension.ExtensionExecutor;
import com.aliyun.openservices.ons.api.OnExceptionContext;
import com.aliyun.openservices.ons.api.SendCallback;
import com.aliyun.openservices.ons.api.SendResult;
import com.bckj.fastboot.core.execution.Execution;
import com.bckj.fastboot.core.execution.ExecutionContext;
import com.bckj.freshnow.common.constant.PaymentMethodConstants;
import com.bckj.freshnow.common.constant.TradeOrderConstants;
import com.bckj.freshnow.order.entity.*;
import com.bckj.freshnow.order.model.CreateTradeOrderRequest;
import com.bckj.freshnow.order.model.TradeOrderMsg;
import com.bckj.freshnow.order.repo.TradeBillInfoRepository;
import com.bckj.freshnow.order.repo.TradeBillStatementRepository;
import com.bckj.freshnow.order.trade.fsm.TradeOrderContext;
import com.bckj.freshnow.order.trade.ons.producer.TradeOrderOnsProducer;
import com.bckj.freshnow.payment.model.PayRequest;
import com.bckj.freshnow.payment.model.PayResponse;
import com.bckj.freshnow.payment.pay.extension.PayExtPt;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
@RequiredArgsConstructor
public class CreateTradeOrderBillExecution implements Execution {

    private final TradeBillInfoRepository tradeBillInfoRepository;
    private final TradeBillStatementRepository tradeBillStatementRepository;
    private final TradeOrderOnsProducer tradeOrderMsgProducer;
    private final ExtensionExecutor extensionExecutor;


    @Override
    public void execute(ExecutionContext context) {
        TradeOrderContext ctx = (TradeOrderContext) context;
        TradeBillInfo billInfo = getBillInfo(ctx);
        tradeBillInfoRepository.save(billInfo);
        List<TradeBillStatement> list = getBillStatement(ctx, billInfo, ctx.getParentOrder());
        tradeBillStatementRepository.saveBatch(list);
        if (billInfo.getBillStatus() == TradeOrderConstants.TRADE_BILL_STATUS_PENDING_PAYMENT) {
            //向支付中心发起支付请求
            var payRequest = new PayRequest();
            payRequest.setAppId("1001");
            payRequest.setPaymentMethod(PaymentMethodConstants.WECHAT_PAY_JSAPI);
            payRequest.setAmount(billInfo.getPayableAmount());
            payRequest.setRequestNo(billInfo.getId().toString());
            var payResponse = pay(payRequest);
            if (payResponse.getCode() == 500) {
                throw new RuntimeException(payResponse.getMessage());
            }
            //支付超时消息
            tradeOrderMsgProducer.afterSend(
                    TradeOrderMsg.create()
                            .setOrderId(billInfo.getOrderId())
                            .setDelaySeconds(86400)
                    , new SendCallback() {
                        @Override
                        public void onSuccess(SendResult sendResult) {

                        }

                        @Override
                        public void onException(OnExceptionContext onExceptionContext) {

                        }
                    });
        }
    }

    private PayResponse pay(PayRequest request) {
        BizScenario bizScenario = BizScenario.valueOf("PAY", "WX", "JSAPI");
        return extensionExecutor.execute(PayExtPt.class, bizScenario, ext -> ext.pay(request));
    }

    private TradeBillInfo getBillInfo(TradeOrderContext ctx) {
        TradeBillInfo billInfo = new TradeBillInfo();
        TradeParentOrder parentOrder = ctx.getParentOrder();
        billInfo.setOrderId(parentOrder.getId());
        billInfo.setIsParent(1);
        billInfo.setBillType(TradeOrderConstants.TRADE_BILL_TYPE_PREPAY);
        billInfo.setBillAmount(parentOrder.getTotalAmount());
        billInfo.setDiscountAmount(parentOrder.getDiscountAmount());
        billInfo.setPayableAmount(parentOrder.getPayAmount());
        billInfo.setPendingAmount(parentOrder.getPayAmount());
        int billStatus = TradeOrderConstants.TRADE_BILL_STATUS_PENDING_PAYMENT;
        CreateTradeOrderRequest request = (CreateTradeOrderRequest) ctx.getRequest();
        if (request.getPaymentMethod() != null && request.getPaymentMethod() == TradeOrderConstants.TRADE_BILL_STATEMENT_PAYMENT_METHOD_MONTHLY) {
            billStatus = TradeOrderConstants.TRADE_BILL_STATUS_PAID;
        }
        billInfo.setBillStatus(billStatus);
        return billInfo;
    }

    private List<TradeBillStatement> getBillStatement(TradeOrderContext ctx, TradeBillInfo billInfo, TradeParentOrder parentOrder) {
        List<TradeBillStatement> list = new ArrayList<>();
        CreateTradeOrderRequest request = (CreateTradeOrderRequest) ctx.getRequest();
        int paymentStatus = TradeOrderConstants.TRADE_BILL_STATEMENT_STATUS_PENDING_PAYMENT;
        if (request.getPaymentMethod() != null && request.getPaymentMethod() == TradeOrderConstants.TRADE_BILL_STATEMENT_PAYMENT_METHOD_MONTHLY) {
            //月结 支付状态为完成
            paymentStatus = TradeOrderConstants.TRADE_BILL_STATEMENT_STATUS_PAID;
        }
        //营销
        for (TradeOrder tradeOrder : parentOrder.getOrderList()) {
            if (CollUtil.isNotEmpty(tradeOrder.getMarketingInfoList())) {
                for (TradeMarketingInfo marketingInfo : tradeOrder.getMarketingInfoList()) {
                    TradeBillStatement billStatement = new TradeBillStatement();
                    billStatement.setBillId(billInfo.getId());
                    billStatement.setPaymentStatus(paymentStatus);
                    //优惠
                    billStatement.setStatementType(TradeOrderConstants.TRADE_BILL_STATEMENT_TYPE_DISCOUNT);
                    billStatement.setPaymentMethod(marketingType2PaymentMethod(marketingInfo.getMarketingType()));
                    billStatement.setAmount(marketingInfo.getDiscountAmount());
                    list.add(billStatement);
                }
            }
        }
        //应付
        TradeBillStatement billStatement = new TradeBillStatement();
        billStatement.setBillId(billInfo.getId());
        billStatement.setPaymentStatus(paymentStatus);
        //支付
        billStatement.setStatementType(TradeOrderConstants.TRADE_BILL_STATEMENT_TYPE_PAYMENT);
        billStatement.setPaymentMethod(request.getPaymentMethod());
        billStatement.setPaymentAccount(request.getPaymentAccount());
        billStatement.setAmount(billInfo.getPendingAmount());
        list.add(billStatement);
        return list;
    }

    private int marketingType2PaymentMethod(int marketingType) {
        //营销类型，1：用户身份 2：优惠券 3：积分 4：活动 5：会员卡
        return switch (marketingType) {
            case 1 -> 3;
            case 2 -> 4;
            case 3 -> 5;
            case 4 -> 6;
            case 5 -> 7;
            default -> 0;
        };
    }


}
